use derive_builder::Builder;
use serde::{Deserialize, Serialize};

use crate::error::Error;
use crate::mapper::ValueMapper;
use crate::modeling::{
    ClassAttributePersistence, ClassPersistence, ClassPersistenceBuilder, ClassPersistenceGetter,
    ClassRelationGetter, CollectionType, Value, ValueSize, ValueType,
};

use super::{
    Class, ClassBuilder, ClassGetter, ClassRelation, ClassRelationBuilder, RelationRelatedType,
};

pub const CLASS_ATTRIBUTE_CLASS_IDENTIFIER: &'static str = "g01_class_attribute";

pub const CLASS_ATTRIBUTE_CLASS_NAME: &'static str = "class_attribute";

pub const CLASS_ATTRIBUTE_TABLE_NAME: &'static str = "_g01_meta_class_attributes";

#[derive(Debug, Serialize, Deserialize, Clone, Builder, PartialEq)]
#[builder(name = "ClassAttributeBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct ClassAttribute {
    /// id
    pub id: i64,
    /// class identifier
    pub class_identifier: String,
    /// code
    pub identifier: String,
    /// 名称
    pub name: String,
    /// 名称
    pub title: String,
    /// primary_key
    pub is_key: bool,
    /// 类型
    pub data_type: ValueType,
    /// 是否持久化
    pub is_persistent: bool,
    /// 存储类型
    pub storage_type: Option<ValueType>,
    /// 持久化
    pub persistence: Option<String>,
    /// 集合类型
    pub collection_type: CollectionType,
    /// is_number
    pub is_number: bool,
    /// 自增
    pub is_autoincrement: bool,
    /// is_number
    pub value_size: ValueSize,
    /// unit
    pub unit: Option<String>,
    /// default value
    pub default_value: Option<String>,
    /// is_nullable
    pub is_nullable: bool,
    /// position
    pub position: i32,
    /// scope
    pub scope: Option<String>,
    /// 附加信息
    pub options: Option<String>,
    /// 备注
    pub description: String,
    // 创建时间
    pub created_at: i64,
    // 更新时间
    pub updated_at: i64,
}

impl Default for ClassAttribute {
    fn default() -> Self {
        Self {
            id: 0,
            class_identifier: String::new(),
            identifier: String::new(),
            name: String::new(),
            title: String::new(),
            is_key: false,
            data_type: ValueType::String,
            is_persistent: true,
            storage_type: None,
            persistence: None,
            collection_type: CollectionType::Single,
            is_number: false,
            is_autoincrement: false,
            value_size: ValueSize::Medium,
            unit: Some(String::new()),
            default_value: Some(String::new()),
            is_nullable: false,
            position: 0,
            scope: Some(String::new()),
            options: Some(String::new()),
            description: String::new(),
            created_at: 0,
            updated_at: 0,
        }
    }
}
impl ValueMapper for ClassAttribute {}
//
crate::impl_from_value!(ClassAttribute);
crate::impl_class_persistence_getter!(ClassAttribute, CLASS_ATTRIBUTE_TABLE_NAME);
crate::impl_class_relations_getter!(
    ClassAttribute,
    vec![ClassRelationBuilder::default()
        .src_identifier(Class::get_identifier()?)
        .target_identifier(Self::get_identifier()?)
        .related_type(RelationRelatedType::Keys)
        .related_at("class_identifier")
        .build()?,]
);

impl ClassGetter for ClassAttribute {
    fn get_name() -> anyhow::Result<String> {
        Ok(String::from(CLASS_ATTRIBUTE_CLASS_NAME))
    }

    fn get_identifier() -> anyhow::Result<String> {
        Ok(String::from(CLASS_ATTRIBUTE_CLASS_IDENTIFIER))
    }
    fn get_class() -> anyhow::Result<Class> {
        let mut attribute_builder = ClassAttributeBuilder::default();
        attribute_builder.class_identifier(CLASS_ATTRIBUTE_CLASS_IDENTIFIER);

        let mut commons = super::common_attributes_with_builder(&attribute_builder)?;
        let mut append = vec![
            attribute_builder
                .clone()
                .name("class_identifier")
                .title("类型")
                .position(10)
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("is_key")
                .title("主键")
                .position(11)
                .data_type(ValueType::Boolean)
                .build()?,
            attribute_builder
                .clone()
                .name("data_type")
                .title("数据类型")
                .position(12)
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("collection_type")
                .title("集合")
                .position(13)
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("is_number")
                .title("数字")
                .position(14)
                .data_type(ValueType::Boolean)
                .build()?,
            attribute_builder
                .clone()
                .name("storage_type")
                .title("存储类型")
                .position(13)
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("is_persistent")
                .title("持久化")
                .position(13)
                .data_type(ValueType::Boolean)
                .build()?,
            attribute_builder
                .clone()
                .name("persistence")
                .title("持久化信息")
                .position(13)
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("unit")
                .title("单位")
                .position(15)
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("is_autoincrement")
                .title("自增")
                .position(15)
                .data_type(ValueType::Boolean)
                .build()?,
            attribute_builder
                .clone()
                .name("value_size")
                .title("大小")
                .position(16)
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("default_value")
                .title("默认值")
                .position(17)
                .data_type(ValueType::String)
                .build()?,
            attribute_builder
                .clone()
                .name("is_nullable")
                .title("为空")
                .position(18)
                .data_type(ValueType::Boolean)
                .build()?,
            attribute_builder
                .clone()
                .name("position")
                .title("顺序")
                .position(19)
                .data_type(ValueType::Number)
                .build()?,
            attribute_builder
                .clone()
                .name("scope")
                .title("范围")
                .position(20)
                .data_type(ValueType::String)
                .build()?,
        ];
        append.append(&mut commons);
        append.sort_by(|a, b| a.position.cmp(&b.position));
        let clazz = ClassBuilder::default()
            .identifier(CLASS_ATTRIBUTE_CLASS_IDENTIFIER)
            .name(CLASS_ATTRIBUTE_CLASS_NAME)
            .data_is_type(false)
            .is_persistent(true)
            .primary_key(String::from("identifier"))
            .attributes(append)
            .build()?;
        Ok(clazz)
    }
}

impl ClassAttribute {
    pub fn get_storage_type(&self) -> ValueType {
        if let Some(t) = &self.storage_type {
            t.clone()
        } else {
            self.data_type.clone()
        }
    }
    pub fn get_storage_name(&self) -> String {
        if let Some(t) = &self.persistence {
            t.clone()
        } else {
            self.name.clone()
        }
    }
}
